package algorithms.larspetrus.maker;

import database.*;

import java.util.Date;

public class LarsPetrusFirstStepAlgorithmMaker2 {
	private static final String FINAL_STRING = ".ww.ww...............gg.gg...................rr.rr....";
	private static final String[] MOVES = {
		"R", "L", "U", "D", "F", "B",
		"R'", "L'", "U'", "D'", "F'", "B'",
		"R2", "L2", "U2", "D2", "F2", "B2"
	};
	private static final String[] MOVES_R = { "L", "U", "D", "F", "B", "L'", "U'", "D'", "F'", "B'", "L2", "U2", "D2", "F2", "B2" };
	private static final String[] MOVES_L = { "R", "U", "D", "F", "B", "R'", "U'", "D'", "F'", "B'", "R2", "U2", "D2", "F2", "B2" };
	private static final String[] MOVES_U = { "R", "L", "D", "F", "B", "R'", "L'", "D'", "F'", "B'", "R2", "L2", "D2", "F2", "B2" };
	private static final String[] MOVES_D = { "R", "L", "U", "F", "B", "R'", "L'", "U'", "F'", "B'", "R2", "L2", "U2", "F2", "B2" };
	private static final String[] MOVES_F = { "R", "L", "U", "D", "B", "R'", "L'", "U'", "D'", "B'", "R2", "L2", "U2", "D2", "B2" };
	private static final String[] MOVES_B = { "R", "L", "U", "D", "F", "R'", "L'", "U'", "D'", "F'", "R2", "L2", "U2", "D2", "F2" };
	
	private static final int[] transR = { 0, 1, 27, 3, 4, 28, 6, 7, 29, 9, 10, 11, 12, 13, 14, 24, 25, 26, 18, 19, 20, 21, 22, 23, 8, 5, 2, 17, 16, 15, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 51, 48, 45, 52, 49, 46, 53, 50, 47 };
	private static final int[] transL = { 20, 1, 2, 19, 4, 5, 18, 7, 8, 35, 34, 33, 12, 13, 14, 15, 16, 17, 9, 10, 11, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 0, 3, 6, 42, 39, 36, 43, 40, 37, 44, 41, 38, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
	private static final int[] transF = { 45, 46, 47, 3, 4, 5, 6, 7, 8, 36, 10, 11, 39, 13, 14, 42, 16, 17, 24, 21, 18, 25, 22, 19, 26, 23, 20, 27, 28, 29, 30, 31, 32, 33, 34, 35, 2, 37, 38, 1, 40, 41, 0, 43, 44, 15, 12, 9, 48, 49, 50, 51, 52, 53 };
	private static final int[] transB = { 0, 1, 2, 3, 4, 5, 44, 41, 38, 9, 10, 53, 12, 13, 52, 15, 16, 51, 18, 19, 20, 21, 22, 23, 24, 25, 26, 33, 30, 27, 34, 31, 28, 35, 32, 29, 36, 37, 11, 39, 40, 14, 42, 43, 17, 45, 46, 47, 48, 49, 50, 6, 7, 8 };
	private static final int[] transU = { 6, 3, 0, 7, 4, 1, 8, 5, 2, 9, 10, 11, 12, 13, 14, 15, 16, 17, 38, 19, 20, 37, 22, 23, 36, 25, 26, 45, 28, 29, 48, 31, 32, 51, 34, 35, 33, 30, 27, 39, 40, 41, 42, 43, 44, 18, 46, 47, 21, 49, 50, 24, 52, 53 };
	private static final int[] transD = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 15, 12, 9, 16, 13, 10, 17, 14, 11, 18, 19, 47, 21, 22, 50, 24, 25, 53, 27, 28, 44, 30, 31, 43, 33, 34, 42, 36, 37, 38, 39, 40, 41, 26, 23, 20, 45, 46, 29, 48, 49, 32, 51, 52, 35 };
	private static final int[] transR2 = { 0, 1, 17, 3, 4, 16, 6, 7, 15, 9, 10, 11, 12, 13, 14, 8, 5, 2, 18, 19, 20, 21, 22, 23, 29, 28, 27, 26, 25, 24, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 53, 52, 51, 50, 49, 48, 47, 46, 45 };
	private static final int[] transL2 = { 11, 1, 2, 10, 4, 5, 9, 7, 8, 6, 3, 0, 12, 13, 14, 15, 16, 17, 35, 34, 33, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 20, 19, 18, 44, 43, 42, 41, 40, 39, 38, 37, 36, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
	private static final int[] transF2 = { 15, 12, 9, 3, 4, 5, 6, 7, 8, 2, 10, 11, 1, 13, 14, 0, 16, 17, 26, 25, 24, 23, 22, 21, 20, 19, 18, 27, 28, 29, 30, 31, 32, 33, 34, 35, 47, 37, 38, 46, 40, 41, 45, 43, 44, 42, 39, 36, 48, 49, 50, 51, 52, 53 };
	private static final int[] transB2 = { 0, 1, 2, 3, 4, 5, 17, 14, 11, 9, 10, 8, 12, 13, 7, 15, 16, 6, 18, 19, 20, 21, 22, 23, 24, 25, 26, 35, 34, 33, 32, 31, 30, 29, 28, 27, 36, 37, 53, 39, 40, 52, 42, 43, 51, 45, 46, 47, 48, 49, 50, 44, 41, 38 };
	private static final int[] transU2 = { 8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 27, 19, 20, 30, 22, 23, 33, 25, 26, 18, 28, 29, 21, 31, 32, 24, 34, 35, 51, 48, 45, 39, 40, 41, 42, 43, 44, 38, 46, 47, 37, 49, 50, 36, 52, 53 };
	private static final int[] transD2 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 17, 16, 15, 14, 13, 12, 11, 10, 9, 18, 19, 29, 21, 22, 32, 24, 25, 35, 27, 28, 20, 30, 31, 23, 33, 34, 26, 36, 37, 38, 39, 40, 41, 53, 50, 47, 45, 46, 44, 48, 49, 43, 51, 52, 42 };
	private static final int[] transR3 = { 0, 1, 26, 3, 4, 25, 6, 7, 24, 9, 10, 11, 12, 13, 14, 29, 28, 27, 18, 19, 20, 21, 22, 23, 15, 16, 17, 2, 5, 8, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 47, 50, 53, 46, 49, 52, 45, 48, 51 };
	private static final int[] transL3 = { 33, 1, 2, 34, 4, 5, 35, 7, 8, 18, 19, 20, 12, 13, 14, 15, 16, 17, 6, 3, 0, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 11, 10, 9, 38, 41, 44, 37, 40, 43, 36, 39, 42, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
	private static final int[] transF3 = { 42, 39, 36, 3, 4, 5, 6, 7, 8, 47, 10, 11, 46, 13, 14, 45, 16, 17, 20, 23, 26, 19, 22, 25, 18, 21, 24, 27, 28, 29, 30, 31, 32, 33, 34, 35, 9, 37, 38, 12, 40, 41, 15, 43, 44, 0, 1, 2, 48, 49, 50, 51, 52, 53 };
	private static final int[] transB3 = { 0, 1, 2, 3, 4, 5, 51, 52, 53, 9, 10, 38, 12, 13, 41, 15, 16, 44, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 32, 35, 28, 31, 34, 27, 30, 33, 36, 37, 8, 39, 40, 7, 42, 43, 6, 45, 46, 47, 48, 49, 50, 17, 14, 11 };
	private static final int[] transU3 = { 2, 5, 8, 1, 4, 7, 0, 3, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 45, 19, 20, 48, 22, 23, 51, 25, 26, 38, 28, 29, 37, 31, 32, 36, 34, 35, 24, 21, 18, 39, 40, 41, 42, 43, 44, 27, 46, 47, 30, 49, 50, 33, 52, 53 };
	private static final int[] transD3 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 14, 17, 10, 13, 16, 9, 12, 15, 18, 19, 44, 21, 22, 43, 24, 25, 42, 27, 28, 47, 30, 31, 50, 33, 34, 53, 36, 37, 38, 39, 40, 41, 35, 32, 29, 45, 46, 20, 48, 49, 23, 51, 52, 26 };
	
	public static void main(String[] args) {
		Date oldDate = new Date();
		Date newDate = null;
		int i = 67100671;
        
		while (true) {
			int temp = i += 2;
			String out = MOVES[temp % 18] + " ";
			char lastMove = out.charAt(0);
			temp = temp / 18;
			while (temp != 0) {
				String lastMoveString = getMoveByNumber(temp % 15, lastMove) + " ";
				out += lastMoveString;
				lastMove = lastMoveString.charAt(0);
				temp = temp / 15;
			}
			
			String initString = getNormalizedString(executeMovesList(FINAL_STRING, out));
			
			DBHandler.getInstance().insertPattern(initString, getReverseExecutedMovesList(out));
			
			if (i % 100001 == 0) {
				newDate = new Date();
				System.out.println(i + ": " + (newDate.getTime() - oldDate.getTime()) + "ms : " + out);
				oldDate = new Date();
			}
		}
	}
	
	private static String getMoveByNumber(int number, char lastMove) {
		switch (lastMove) {
			case 'R': return MOVES_R[number];
			case 'L': return MOVES_L[number];
			case 'U': return MOVES_U[number];
			case 'D': return MOVES_D[number];
			case 'F': return MOVES_F[number];
			case 'B': return MOVES_B[number];
		}
		return "";
	}
	
	private static String executeMovesList(String input, String movesList) {
		String[] splitted = movesList.split(" ");
		String output = input;
		for (int i = splitted.length - 1; i >= 0; i--) {
			output = executeMove(output, splitted[i]);
		}
		return output;
	}
	
	private static String executeMove(String input, String str) {
		String movesList = str.trim();
		int[] trans = null;
		
		if (movesList.equals("R")) {
			trans = transR;
		} else if (movesList.equals("L")) {
			trans = transL;
		} else if (movesList.equals("F")) {
			trans = transF;
		} else if (movesList.equals("B")) {
			trans = transB;
		} else if (movesList.equals("U")) {
			trans = transU;
		} else if (movesList.equals("D")) {
			trans = transD;
		} else if (movesList.equals("R'")) {
			trans = transR3;
		} else if (movesList.equals("L'")) {
			trans = transL3;
		} else if (movesList.equals("F'")) {
			trans = transF3;
		} else if (movesList.equals("B'")) {
			trans = transB3;
		} else if (movesList.equals("U'")) {
			trans = transU3;
		} else if (movesList.equals("D'")) {
			trans = transD3;
		} else if (movesList.equals("R2")) {
			trans = transR2;
		} else if (movesList.equals("L2")) {
			trans = transL2;
		} else if (movesList.equals("F2")) {
			trans = transF2;
		} else if (movesList.equals("B2")) {
			trans = transB2;
		} else if (movesList.equals("U2")) {
			trans = transU2;
		} else if (movesList.equals("D2")) {
			trans = transD2;
		}
		String output = "";
		for (int j = 0; j < 54; j++) {
			output += input.charAt(trans[j]);
		}
		return output;
	}
	
	private static String getReverseExecutedMovesList(String input) {
		String[] splitted = input.split(" ");
		String output = "";
		
		for (int i = splitted.length - 1; i >= 0; i--) {
			if (splitted[i].trim().equals("R")) output += "R'";
			if (splitted[i].trim().equals("L")) output += "L'";
			if (splitted[i].trim().equals("F")) output += "F'";
			if (splitted[i].trim().equals("B")) output += "B'";
			if (splitted[i].trim().equals("U")) output += "U'";
			if (splitted[i].trim().equals("D")) output += "D'";
			if (splitted[i].trim().equals("R'")) output += "R";
			if (splitted[i].trim().equals("L'")) output += "L";
			if (splitted[i].trim().equals("F'")) output += "F";
			if (splitted[i].trim().equals("B'")) output += "B";
			if (splitted[i].trim().equals("U'")) output += "U";
			if (splitted[i].trim().equals("D'")) output += "D";
			if (splitted[i].trim().equals("R2")) output += "R2";
			if (splitted[i].trim().equals("L2")) output += "L2";
			if (splitted[i].trim().equals("F2")) output += "F2";
			if (splitted[i].trim().equals("B2")) output += "B2";
			if (splitted[i].trim().equals("U2")) output += "U2";
			if (splitted[i].trim().equals("D2")) output += "D2";
			if (splitted[i].trim().equals("X")) output += "X'";
			if (splitted[i].trim().equals("Y")) output += "Y'";
			if (splitted[i].trim().equals("Z")) output += "Z'";
			if (splitted[i].trim().equals("X'")) output += "X";
			if (splitted[i].trim().equals("Y'")) output += "Y";
			if (splitted[i].trim().equals("Z'")) output += "Z";
			if (splitted[i].trim().equals("X2")) output += "X2";
			if (splitted[i].trim().equals("Y2")) output += "Y2";
			if (splitted[i].trim().equals("Z2")) output += "Z2";
			output += " ";
		}
		return output;
	}
	
	public static String getNormalizedString(String input) {
		String output = new String(input);
		int j = 0;
		for (int i = 0; i < input.length(); i++) {
			char c = output.charAt(i);
			if (!Character.isDigit(c) && c != '.') {
				output = output.replaceAll(c + "", j++ + "");
			}
		}
		return output;
	}
	
	public static String getNormalizedMovesList(String movesList) {
		String[][] replacingStrings = {
				{ "  ", " " }, {"R R ", "R2 "}, {"R' R'", "R2 "}, {"R' R ", " "}, {"R R' ", " "}, {"R2 R ", "R' "},
				{"R2 R' ", "R "}, {"R R2 ", "R' "}, {"R' R2 ", "R "}, {"R2 R2 ", " "},
				{"L L ", "L2 "}, {"L' L' ", "L2 "}, {"L' L ", " "}, {"L L' ", " "}, {"L2 L ", "L' "},
				{"L2 L' ", "L "}, {"L L2 ", "L' "}, {"L' L2 ", "L "}, {"L2 L2 ", " "},
				{"F F ", "F2 "}, {"F' F' ", "F2 "}, {"F' F ", " "}, {"F F' ", " "}, {"F2 F ", "F' "},
				{"F2 F' ", "F "}, {"F F2 ", "F' "}, {"F' F2 ", "F "}, {"F2 F2 ", " "},
				{"B B ", "B2 "}, {"B' B' ", "B2 "}, {"B' B ", " "}, {"B B' ", " "}, {"B2 B ", "B' "},
				{"B2 B' ", "B "}, {"B B2 ", "B' "}, {"B' B2 ", "B "}, {"B2 B2 ", " "},
				{"U U ", "U2 "}, {"U' U' ", "U2 "}, {"U' U ", " "}, {"U U' ", " "}, {"U2 U ", "U' "},
				{"U2 U' ", "U "}, {"U U2 ", "U' "}, {"U' U2 ", "U "}, {"U2 U2 ", " "},
				{"D D ", "D2 "}, {"D' D' ", "D2 "}, {"D' D ", " "}, {"D D' ", " "}, {"D2 D ", "D' "},
				{"D2 D' ", "D "}, {"D D2 ", "D' "}, {"D' D2 ", "D "}, {"D2 D2 ", " "},
				{"X X ", "X2 "}, {"X' X' ", "X2 "}, {"X' X ", " "}, {"X X' ", " "}, {"X2 X ", "X' "},
				{"X2 X' ", "X "}, {"X X2 ", "X' "}, {"X' X2 ", "X "}, {"X2 X2 ", " "},
				{"Y Y ", "Y2 "}, {"Y' Y' ", "Y2 "}, {"Y' Y ", " "}, {"Y Y' ", " "}, {"Y2 Y ", "Y' "},
				{"Y2 Y' ", "Y "}, {"Y Y2 ", "Y' "}, {"Y' Y2 ", "Y "}, {"Y2 Y2 ", " "},
				{"Z Z ", "Z2 "}, {"Z' Z' ", "Z2 "}, {"Z' Z ", " "}, {"Z Z' ", " "}, {"Z2 Z ", "Z' "},
				{"Z2 Z' ", "Z "}, {"Z Z2 ", "Z' "}, {"Z' Z2 ", "Z "}, {"Z2 Z2 ", " "}
		};
		
		StringBuffer normalizedMovesList = new StringBuffer(movesList);
		StringBuffer oldNormalizedMovesList = new StringBuffer();
		
		while (!normalizedMovesList.toString().equals(oldNormalizedMovesList.toString())) {
			oldNormalizedMovesList = new StringBuffer(normalizedMovesList);
			for (int i = 0; i < replacingStrings.length; i++) {
				normalizedMovesList = new StringBuffer(normalizedMovesList.toString().replaceAll(replacingStrings[i][0], replacingStrings[i][1]));
			}
		}
		return normalizedMovesList.toString();
	}
}
